package org.dromara.ai.monitor;

import lombok.Data;
import lombok.EqualsAndHashCode;

import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicLong;

/**
 * AI Provider监控指标
 * 继承基础监控指标，添加Provider特有的监控数据
 *
 * @author ruoyi
 * @date 2024-01-01
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class ProviderMetrics extends BaseMetrics {

    /**
     * Provider名称
     */
    private String providerName;

    /**
     * Provider类型
     */
    private String providerType;

    /**
     * 连接超时次数
     */
    private AtomicLong timeoutCount = new AtomicLong(0);

    /**
     * 限流次数
     */
    private AtomicLong rateLimitCount = new AtomicLong(0);

    /**
     * 配额超限次数
     */
    private AtomicLong quotaExceededCount = new AtomicLong(0);

    /**
     * 服务不可用次数
     */
    private AtomicLong serviceUnavailableCount = new AtomicLong(0);

    /**
     * 最后成功请求时间
     */
    private LocalDateTime lastSuccessTime;

    /**
     * 最后失败请求时间
     */
    private LocalDateTime lastFailureTime;

    /**
     * 连续失败次数
     */
    private AtomicLong consecutiveFailures = new AtomicLong(0);

    /**
     * Provider可用性状态
     */
    private boolean available = true;

    /**
     * 健康检查最后执行时间
     */
    private LocalDateTime lastHealthCheckTime;

    /**
     * 健康检查状态
     */
    private boolean healthCheckPassed = true;

    public ProviderMetrics(String providerName, String providerType) {
        this.providerName = providerName;
        this.providerType = providerType;
        this.lastSuccessTime = LocalDateTime.now();
        this.lastHealthCheckTime = LocalDateTime.now();
    }

    /**
     * 增加超时次数
     */
    public void incrementTimeout() {
        timeoutCount.incrementAndGet();
        incrementFailedRequests();
        updateFailureInfo();
    }

    /**
     * 增加限流次数
     */
    public void incrementRateLimit() {
        rateLimitCount.incrementAndGet();
        incrementFailedRequests();
        updateFailureInfo();
    }

    /**
     * 增加配额超限次数
     */
    public void incrementQuotaExceeded() {
        quotaExceededCount.incrementAndGet();
        incrementFailedRequests();
        updateFailureInfo();
    }

    /**
     * 增加服务不可用次数
     */
    public void incrementServiceUnavailable() {
        serviceUnavailableCount.incrementAndGet();
        incrementFailedRequests();
        updateFailureInfo();
    }

    /**
     * 记录成功请求
     */
    public void recordSuccess() {
        incrementSuccessRequests();
        lastSuccessTime = LocalDateTime.now();
        consecutiveFailures.set(0);
        updateAvailability();
    }

    /**
     * 记录失败请求
     */
    public void recordFailure() {
        incrementFailedRequests();
        updateFailureInfo();
    }

    /**
     * 更新失败信息
     */
    private void updateFailureInfo() {
        lastFailureTime = LocalDateTime.now();
        consecutiveFailures.incrementAndGet();
        updateAvailability();
    }

    /**
     * 更新可用性状态
     */
    private void updateAvailability() {
        // 连续失败超过10次则标记为不可用
        if (consecutiveFailures.get() >= 10) {
            available = false;
        } else if (consecutiveFailures.get() == 0) {
            available = true;
        }
    }

    /**
     * 更新健康检查状态
     */
    public void updateHealthCheck(boolean passed) {
        this.healthCheckPassed = passed;
        this.lastHealthCheckTime = LocalDateTime.now();
        if (!passed) {
            available = false;
        }
    }

    /**
     * 获取Provider健康分数 (0-100)
     */
    public double getHealthScore() {
        if (!available || !healthCheckPassed) {
            return 0.0;
        }

        double successRate = getSuccessRate();
        double timeoutRate = getTotalRequests() > 0 ? 
            (double) timeoutCount.get() / getTotalRequests() * 100 : 0;
        double rateLimitRate = getTotalRequests() > 0 ? 
            (double) rateLimitCount.get() / getTotalRequests() * 100 : 0;

        // 综合计算健康分数
        double score = successRate;
        score -= timeoutRate * 0.5; // 超时影响权重0.5
        score -= rateLimitRate * 0.3; // 限流影响权重0.3

        return Math.max(0, Math.min(100, score));
    }

    /**
     * 重置指标
     */
    @Override
    public void reset() {
        super.reset();
        timeoutCount.set(0);
        rateLimitCount.set(0);
        quotaExceededCount.set(0);
        serviceUnavailableCount.set(0);
        consecutiveFailures.set(0);
        available = true;
        healthCheckPassed = true;
        lastSuccessTime = LocalDateTime.now();
        lastHealthCheckTime = LocalDateTime.now();
    }
}